﻿using IR.Common.Enums;
using IR.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IR.Model.Models
{
    public class MIdea
    {
        private int _ideaID;
        private MUser _userCreated;
        private MVersion _version;
        private string _title;
        private DateTime _dateCreated;
        private Status _status;
        private string _description;
        private DateTime? _lastUpdated;
        private MUser _userAssigned;
        private Category _category;

        #region ***Properties***
        public int IdeaID
        {
            get { return _ideaID; }
        }

        public MUser UserCreated
        {
            get { return _userCreated; }
            set
            {
                if (value != null)
                    _userCreated = value;
            }
        }

        public MVersion Version
        {
            get { return _version; }
            set
            {
                if (value != null)
                    _version = value;
            }
        }

        public string Title
        {
            get { return _title; }
            set
            {
                if (value != null)
                    _title = value;
            }
        }

        public DateTime DateCreated
        {
            get { return _dateCreated; }
            set
            {
                if (value != null)
                    _dateCreated = value;
            }
        }

        public Status Status
        {
            get { return _status; }
            set
            {
                if (value != null)
                    _status = value;
            }
        }

        public string Description
        {
            get { return _description; }
            set
            {
                if (value != null)
                    _description = value;
            }
        }

        public DateTime? LastUpdated
        {
            get { return _lastUpdated; }
            set
            {
                if (value != null)
                    _lastUpdated = value;
            }
        }

        public MUser UserAssigned
        {
            get { return _userAssigned; }
            set
            {
                if (value != null)
                    _userAssigned = value;
            }
        }

        public Category Category
        {
            get { return _category; }
            set
            {
                if (value != null)
                    _category = value;
            }
        }
        #endregion

        /// <summary>
        /// This will save the current Idea (new or old)
        /// </summary>
        /// <param name="allowOverwrite">Allow updating old ideas</param>
        /// <returns>True if saved</returns>
        public bool Save(bool allowOverwrite = false)
        {
            IREntities context = new IREntities();

            // Set values as these are needed either way
            idea currentIdea = new idea
            {
                ididea = _ideaID,
                user_created = _userCreated.Username,
                version = _version.VersionID,
                title = _title,
                status = (int)_status,
                description = _description,
                last_updated = _lastUpdated,
                user_assigned = _userAssigned.Username,
                category = (int)_category
            };

            // Check if new idea
            idea original = context.ideas.Find(_ideaID);

            if (original == null)
            {
                try
                {
                    context.ideas.Add(currentIdea);
                    context.SaveChanges();
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            else if (allowOverwrite == true)
            {
                try
                {
                    context.Entry(original).CurrentValues.SetValues(currentIdea);
                    context.SaveChanges();
                    return true;
                }
                catch
                {
                    return false;
                }
            }

            return false;
        }

        /// <summary>
        /// Loads and returns a idea (Can be used to initialize)
        /// </summary>
        /// <param name="usernameToLoad">IdeaID to look for</param>
        /// <returns>Null if failed</returns>
        public static MIdea Load(int ideaIDToLoad)
        {
            IREntities context = new IREntities();

            // Search for the idea
            idea original = context.ideas.Find(ideaIDToLoad);

            // If found load it
            if (original == null)
            {
                return null;
            }
            else
            {
                MIdea currentIdea = new MIdea();

                currentIdea._ideaID = original.ididea;
                currentIdea._userCreated = MUser.Load(original.user_created);
                currentIdea._version = MVersion.Load(original.version);
                currentIdea._title = original.title;
                currentIdea._dateCreated = original.date_created;
                currentIdea._status = (Status)original.status;
                currentIdea._description = original.description;
                currentIdea._lastUpdated = original.last_updated;
                currentIdea._userAssigned = MUser.Load(original.user_assigned);
                currentIdea._category = (Category)(original.category ?? 0);

                return currentIdea;
            }
        }

        /// <summary>
        /// Gets all ideas currently in the DB
        /// </summary>
        /// <returns>List of all ideas</returns>
        private static List<MIdea> GetAllIdeas()
        {
            IREntities context = new IREntities();

            List<idea> rowList = context.ideas.Select(v => v).ToList();
            List<MIdea> returnList = new List<MIdea>(10);

            foreach (idea row in rowList)
            {
                MIdea currentIdea = new MIdea();

                currentIdea._ideaID = row.ididea;
                currentIdea._userCreated = MUser.Load(row.user_created);
                currentIdea._version = MVersion.Load(row.version);
                currentIdea._title = row.title;
                currentIdea._dateCreated = row.date_created;
                currentIdea._status = (Status)row.status;
                currentIdea._description = row.description;
                currentIdea._lastUpdated = row.last_updated;
                currentIdea._userAssigned = MUser.Load(row.user_assigned);
                currentIdea._category = (Category)(row.category ?? 0);

                returnList.Add(currentIdea);
            }

            return returnList;
        }

        /// <summary>
        /// Runs a query on the version table based on a Dictionary you pass in
        /// </summary>
        /// <param name="queries">Dictonary... key = column name, value = value in column</param>
        /// <returns>List of MIdea matching all params, all if null param</returns>
        public static List<MIdea> QueryIdeas(Dictionary<string, object> queries)
        {
            IREntities context = new IREntities();

            var listOfProperties = typeof(MIdea).GetProperties().ToList();

            List<MIdea> returnIdeas = GetAllIdeas();

            foreach (KeyValuePair<string, object> currentQuery in queries)
            {
                // Gets the current property (column) by stripping off the opening part that defines the namespace
                var currentProperty = listOfProperties
                    .Where(p => p.ToString().Split(' ').ElementAtOrDefault(1) == currentQuery.Key).FirstOrDefault();
                // Filters 'in' all rows that have the column value asked for
                //(so if multiple values are asked for it only returns rows with all values asked for)
                returnIdeas = returnIdeas.Where(v => currentProperty.GetValue(v).ToString() == currentQuery.Value.ToString()).ToList();
            }

            return returnIdeas;
        }
    }
}
